package com.shihb.creationalpatterns;

import java.lang.reflect.Constructor;

/**
 *Description:23种设计模式之单例模式
 * 单例模式核心思想：构造器私有
 *Version:1.0.0
 *@author shihb
 *@date 2020/4/20 14:49
 */
public class SingletonPattern {

  public static void main(String[] args) throws Exception, InstantiationException {
    Lazy lazy1 = Lazy.getInstance();
    // 通过反射破坏单例
    Class<Lazy> lazyClass = Lazy.class;
    // 获取无参构造
    Constructor<Lazy> constructor = lazyClass.getDeclaredConstructor(null);
    // 破坏私有权限
    constructor.setAccessible(true);
    Lazy lazy2 = constructor.newInstance();
    Lazy lazy3 = constructor.newInstance();
    System.out.println(lazy1);
    System.out.println(lazy2);
    System.out.println(lazy3);
//    枚举不会被反射破环
    EnumSingle instance = EnumSingle.INSTANCE;
    Constructor<EnumSingle> declaredConstructor = EnumSingle.class
        .getDeclaredConstructor(String.class, int.class);
    // 破坏私有权限
    declaredConstructor.setAccessible(true);
    EnumSingle instance2 = declaredConstructor.newInstance();
    System.out.println(instance);
    System.out.println(instance2);


  }
}

/**
 * 饿汉式,浪费内存
 */
class Hungry{
  private Hungry() {
  }
  private final static Hungry HUNGRY = new Hungry();
  public static Hungry getInstance(){
    return  HUNGRY;
  }
}
/**
 * 懒汉式
 */
class Lazy {

  private Lazy() {
  }
  /**
   * 不是线程安全,高并发是会多次创建
   * @return
   */
//  private static Lazy lazy;
//  public static Lazy getInstance(){
//    if(lazy==null){
//      lazy=new Lazy();
//    }
//    return lazy;
//  }
  /**
   * 双重检测懒汉式(DCL)
   */
  private volatile static Lazy lazy;

  public static Lazy getInstance() {
    if (lazy == null) {
      synchronized (Lazy.class) {
        if (lazy == null) {
          /**
           * 不是原子性操作
           * 1.分配内存空间
           * 2.执行构造方法，初始化对象
           * 3.把这个对象指向这个空间
           * 存在指针重排，可能造成空指针
           * 解决：对象加关键字volatile避免指针重排
           */
          lazy = new Lazy();
        }
      }
    }
    return lazy;
  }

}
/**
 *  静态内部类
 */
class Holder {
  private Holder(){
  }
  public static Holder getInstance(){
    return InnerClass.HOLDER;
  }
  public static class InnerClass{
    private static final Holder HOLDER = new Holder();
  }
}

/**
 * 以上三种都是不安全的，可以通过反射破坏单例
 * 枚举不会被反射破环,枚举本身也是一个class类
 */
enum EnumSingle{
  INSTANCE;
  public EnumSingle getInstance(){
    return INSTANCE;
  }
}
